<?php


/**
 * Notes:
 * PROJECT_NAME : ERP v1.8 重构erp
 * User: 夏鱼儿<397072174@qq.com>
 * Date: 2024/3/13
 * Time: 17:22
 */

namespace app\admin\controller;

use app\admin\model\GoodsSpec;
use app\admin\validate\GoodsValidate;
use app\admin\validate\ImportGoodsValidate;
use app\service\traits\Crud;
use app\admin\model\Goods as GoodsModel;
use app\admin\model\GoodsCate;
use app\company\model\Goods as GoodsBaseModel;
use Exception;
use PhpOffice\PhpSpreadsheet\IOFactory;
use think\Response;
use app\admin\model\GoodsRule;

class Goods extends Base
{
    private GoodsModel $model;

    use Crud;

    public function initialize()
    {
        parent::initialize();
        $this->model         = new GoodsModel();
        $this->validateClass = GoodsValidate::class;
        $this->withSearch    = "goods_id,status,goods_cate_id,id,name";
    }

    public function format($list): mixed
    {
        return $list->each(function ($item) {
            $item->goods_cate_name = getGoodsCateName($item->goods_cate_id);
        });
    }

    public function detailFormat($info): mixed
    {
        $info->goods_spec      = GoodsSpec::where('goods_id', $info->id)->field('id,name,value')->select();
        $info->goods_rule      = $info->goodsRules()->field('id,spec_name,money,img,status,purchasing_price,weight')->select();
        $info->goods_cate_name = getGoodsCateName($info->goods_cate_id);
        return $info;
    }

    /**
     * 下载模板
     * @return Response
     */
    public function downloadTemplate(): Response
    {
        $sheet = [];
        //标题 目前写在前端了
//        $sheet['title'] = [
//                '商品名称(必填项）', '商品条形码(必填项）', '所属品牌(必选项）', '一级分类（非必选，不选择则默认是其他）', '二级分类（非必选，不选择则默认是其他使用）', '保质期(天）(必填项）', '滞留时间(天)(非必填，不填写默认为null）', '滞销时间(天)(非必填，不填写默认为null）', '临期时间(天)(非必填，不填写默认为null）', '贮藏条件(非必选，不选择默认为常温）', '备注(非必填)', '关键词(非必填)', '单位(必填项）', '规格(必填项）', '供应商(必选项）', '进价(必填项）', '毛利率（%，非必选，只允许输入阿拉伯数字，且最小单位小数点后两位）', '单品（非必选，不选择则默认是否）', '是否选品（非必选，不选择则默认是否）', '重量（kg,非必选，不选填写默认是1)', '长（mm,非必选，不选填写默认是1)', '宽（mm,非必选，不选择则默认是1)', '高（mm,非必选，不选择则默认是1)'
//        ];
        //分类列表
        $sheet['cate_list'] = GoodsCate::status(1)->where('pid', 0)->field('id ,name')->select()->each(function ($item) {
            $item->second_cate = GoodsCate::status(1)->where('pid', $item['id'])->field('id,name')->select();
        });
        return $this->success('下载成功', compact('sheet'));
    }

    /**
     * 导入模板
     * @return Response
     */
    public function import(): Response
    {
        if (!$sheet = request()->param('sheet', '')) return $this->error('数据为空');
        $errorList        = []; // 存放字段错误信息
        $failedImports    = []; // 记录导入失败数据
        $failedImportsNum = 0; // 记录导入失败的数量
        // 开启数据库事务
        $this->model->startTrans();
        try {
            foreach ($sheet as $item) {
                $validate = new ImportGoodsValidate();
                if (!$validate->scene('add')->batch(true)->check($item)) {
                    $errorList[] = $validate->getError();
                    $failedImportsNum++;
                    $failedImports[] = $item;
                    continue;
                }
                //判断分类是否存在
                if (GoodsCate::where('id', $item['goods_cate_id'])->where('pid','<>',0)->count() == 0) {
                    $errorList[] = '分类不存在';
                    $failedImportsNum++;
                    $failedImports[] = $item;
                    continue;
                }

                //判断商品是否存在
                if ($this->model->where('name', $item['name'])->count()) {
                    $errorList[] = '商品已存在';
                    $failedImportsNum++;
                    $failedImports[] = $item;
                    continue;
                }
                //创建商品
                $item['status'] = 2;
                $goods = GoodsBaseModel::create($item);
                $no  = 'GOODS' . getPaddedNumber($goods->id, 10);
                GoodsBaseModel::where('id', $goods->id)->update(['no' => $no]);

                //创建规格
                $spec['goods_id'] = $goods->id;
                $spec['money'] = $item['money'];
                $spec['purchasing_price'] = $item['purchasing_price'];
                GoodsRule::create($spec);

            }
            // 提交事务
            $this->model->commit();
            if ($failedImportsNum > 0) {
                $errorMsg    = "出现" . $failedImportsNum . "条数据导入失败，请下载错误数据并修改重新导入";
                $errorDetail = compact('errorMsg', 'errorList', 'failedImports');
                return $this->error( '部分导入失败', $errorDetail);
            } else {
                return $this->success( '导入成功');
            }
        } catch (\Exception $e) {
            // 发生异常时回滚事务
            $this->model->rollback();
            return $this->error( '服务器内部错误'.$e->getMessage());
        }
    }

    public function importExcel(): Response
    {
        $file = request()->file('file'); // 获取上传的文件
        if (!$file) {
            return $this->error('文件上传失败');
        }
        $reader = IOFactory::createReaderForFile($file);
        $reader->setReadDataOnly(true);
        $spreadsheet = $reader->load($file);
        $sheet = $spreadsheet->getActiveSheet();
        $highestRow = $sheet->getHighestRow();
        $highestColumn = $sheet->getHighestColumn();
        $failedImports = [];
        for ($row = 4; $row <= $highestRow; $row++) {
            // 读取单元格数据
            $data = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, '',
                                         true, true, true);

            $failedImports[] = $data[$row];
        }
        $this->model->startTrans();
        try {
            $this->getFields($failedImports);
            $this->model->commit();
        }catch (Exception $e){
            return $this->error($e->getMessage());
        }
        return $this->success('导入成功');
    }

    private function getFields(array $failedImports): void
    {
        foreach ($failedImports as $item)
        {
            $goods_name = $item['B'];
            $min_code   = $item['I'];
            $max_code   = $item['K'];
            if($min_code && $max_code){
                $row = $this->model->where('name',$goods_name)->find();
                if($row){
                    $row->min_code = $min_code;
                    $row->max_code = $max_code;
                    $row->save();
                }
            }
        }
    }
}